//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>

#include <hook.h>

class NotiCenter : public Hook, public CDeviceDriver {
public:
    NotiCenter(int MaxItem);

    ~NotiCenter();

    CARAPI Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf &buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf &inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    // It's Maybe have no use for the keyboard driver.
    virtual void Dispose() {}
};

NotiCenter::NotiCenter(int MaxItem) : Hook( MaxItem )
{
    return ;
}

NotiCenter::~NotiCenter()
{
    return ;
}

ECode NotiCenter::Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode NotiCenter::Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf &buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode NotiCenter::Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf &inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent)
{
    int eType = (int)nControlCode & 0xffff;
    int nCode = (int)nControlCode >> 16;
    NotifyByIsr(eType, nCode, (void *)inBuffer.GetPayload());
    return NOERROR;
}

static NotiCenter *g_pNotiCenter = NULL;
//BUGBUG: why 2.0 ARM not support user defined construct at global
//static NotiCenter g_NotiCenter(32);

int AddNotify(int EventType, const void *pNotiProc)
{
    g_pNotiCenter->Set(EventType, pNotiProc);
    return 0;
}

void NotifyByIsr(int eType, int nCode, void *pParam)
{
#if 0
    if (eType == EVENT_KEYPAD) {
        unsigned long *pBuf = (unsigned long *)pParam;
        cprintf("======Key 0x%x (%08x)\n", pBuf[1], pBuf[0]);
    }
    else if (eType == EVENT_TOUCH) {
        unsigned long *pBuf = (unsigned long *)pParam;
        cprintf("======Pen 0x%x (%d, %d)\n", pBuf[0], pBuf[1], pBuf[2]);
    }
#endif
    if (g_pNotiCenter) {
        g_pNotiCenter->CallNext(eType, nCode, pParam);
    }
    return;
}

EXTERN IDeviceDriver * CDECL CreateNotiCenter(uint_t uDeviceNo, void *pvParameter)
{
    g_pNotiCenter = new NotiCenter(EVENT_MAX);
    //cprintf("Create NotiCenter %x\n", g_pNotiCenter);
    return (IDeviceDriver *)g_pNotiCenter;
}
